# -*- coding: utf-8 -*-

# 最新版本：V1.1.2

# 功能描述：能够把在word文档中的题目copy到excel后，对excel按照要求重新整理出格式并且存放到另外的excel文件中
# 版本：V1.0
# bug：可以在数据为float类型数据的时候，对小数部分丢失，由于dictLastValue = dictLastValue + "%.0f"%str2导致的
# 开发时间：2016/03/21 凌晨
# 开发者：dong飞秋
# 联系方式：qq 993484988

# 版本：V1.0.1
# 更新日志
# 更新内容：
#		1.如果题目类型为“代码”题，那么就把code存放到txt文件中
#		2.把所有的txt代码文件打包为zip
# 更新日期：2016/03/21
# 更新人员：dong飞秋

# 版本：V1.1
# 更新日志
# 更新内容
# 		1. 添加对 python传递excel文件的名字
# 		2. 生成文件夹
# 		3. 对BCD选项前面添加~ 
#			（要求，ABCD各自占一行，否则不解析）
# 		4. 把填空题的答案合并到题干中，用【】进行包裹
#			（要求，题干中需要填空的地方，使用四个_组成，否则不解析）
# 更新日期：2016/03/21
# 更新人员：dong飞秋

	
# 版本：V1.1.1
# 更新日志
# 更新内容
# 		1. debug，题目序号是纯数字的float类型，不能进行endcode的bug
# 			if type(rowDataList[0]) == type(3.14):
# 				return
# 更新日期：2016/03/22
# 更新人员：dong飞秋

# 版本：V1.1.2
# 更新日志
# 更新内容
#		1. 添加判断要创建的文件夹是否已经存在，如果已存在则就是用这个文件夹，如果这个文件夹中的文件的名字和要创建的文件名相同，则重写此文件
#		2. 添加一些调试信息，进行了优化
# 更新日期：2016/03/22
# 更新人员：dong飞秋

# 版本：V1.1.3
# 更新日志
# 更新内容
#       1>选择题目可以是小写的abcd选项，写入excel时，会被自动替换成大写
#       2>增加写入完成的提示
# 更新日期：2016/03/23
# 更新人员：iOS学院 - YosonHao

# 版本：V1.1.4
# 更新日志
# 更新内容
#       1>按照最新的要求更换了excel的输出顺序
#       2>第一行的内容固定为 '题型	知识体系名称 知识点	关键字	题干	选项	答案	答案说明	难度'
# 更新日期：2016/04/23
# 更新人员：iOS学院 - YosonHao

# 版本：V1.1.5
# 更新日志
# 更新内容
#       1>根据总裁办的要求，修改'题型	知识体系名称 知识点	关键字	题干	选项	答案	答案说明	难度'的先后顺序
# 更新日期：2016/05/04
# 更新人员：iOS学院 - dong飞秋



import xlrd
import xlwt
import types
import codecs
import zipfile
import os
import sys


examStartId = 1
examEndId = 1
rowNumInOneExam = 1
oneExamStartEndFlag = 0 # 1表示开始，0表示没有遇到真正的题目开始
oneExamDataDict = {} # 用来对一道题目的数据进行封装
dictLastKey = ''
dictLastValue = ''

# 用来存储路径，因为要新建立一个文件夹，所以要重新赋值
dirctName = '' 
# 文件夹的名字，没有路径，只有名字
folderName = ''

# 将要解析的excel文件名
needToAnalysisExcelName = ''

# excel文件的句柄
excelHand = ''
# 打开的sheet表句柄
sheetHand = ''

# 标记是否有 “代码”类型的题目，如果没有那么就不要打包zip
needToZipFlag = 0

#把“代码”类型题目的答案写入到txt文件中
def saveProgramToTxt(filePath, fileName, content):

	file_object = codecs.open(filePath + '/' + fileName, 'w', 'utf-8')
	file_object.write(fileName + '\n')
	file_object.write(content)
	file_object.close() 

#处理ABCD选项，把B，C，D的前面添加一个~
def dealWithOptions(options):
	
	optionsResult = ''

	#增加小写字母判断 -YosonHao
	findIndexA = options.find('A')
	if findIndexA == -1:
		findIndexA = options.find('a')

	findIndexB = options.find('\nB')
	if findIndexB == -1:
		findIndexB = options.find('\nb')

	findIndexC = options.find('\nC')
	if findIndexC == -1:
		findIndexC = options.find('\nc')

	findIndexD = options.find('\nD')
	if findIndexD == -1:
		findIndexD = options.find('\nd')

	optionsResult += options[findIndexA].upper()
	optionsResult += options[findIndexA+1:findIndexB]
	optionsResult += '~' + options[findIndexB+1].upper()
	optionsResult += options[findIndexB+2:findIndexC]
	optionsResult += '~' + options[findIndexC+1].upper()
	optionsResult += options[findIndexC+2:findIndexD]
	optionsResult += '~' + options[findIndexD+1].upper()
	optionsResult += options[findIndexD+2:]

	return optionsResult

#处理填空题，把答案放到题干中，并且用【】包裹起来
def dealWithBlank(quesiont, result):

	# 存储经过处理过后的题干
	blankResult = ''

	# 按照一个换行符进行切割字符串
	resultList = result.split('\n')

	# print resultList[0]

	# 根据切割出来的答案的个数，来进行替换 题干中的____
	x = 0;
	qIndex = quesiont.find('____')
	while qIndex!=-1:
		qTemp = '';
		qTemp = quesiont[:qIndex+4]
		quesiont = quesiont[qIndex+4:]
		blankResult += qTemp.replace('____', '【' + str(resultList[x]) + '】')
		x += 1
		qIndex = quesiont.find('____')

	blankResult += quesiont

	return blankResult

#写excel
def write_excel(examEndId, oneExamDataDict):
	global sheetHand

	keyStringName = []
	for k in oneExamDataDict:
		# print "dict[%s] =" % k,oneExamDataDict[k]
		keyStringName.append(k);
		# print k, '===>' + oneExamDataDict[k] + '<===';

	# 向一行数写入一道题目
	# 写入数据到单元格
	sheetHand.write(examEndId-1, 1, 'iOS学科')

	if oneExamDataDict.has_key('知识点'):
		sheetHand.write(examEndId-1, 2, oneExamDataDict['知识点'])
	elif oneExamDataDict.has_key('所属知识点'):
		sheetHand.write(examEndId-1, 2, oneExamDataDict['所属知识点'])

	sheetHand.write(examEndId-1, 3, oneExamDataDict['关键字'])
	sheetHand.write(examEndId-1, 0, oneExamDataDict['题目类型'])


	sheetHand.write(examEndId-1, 4, oneExamDataDict['题干'])
	
	if oneExamDataDict.has_key('选项'):
		optionsResult = dealWithOptions(oneExamDataDict['选项'])
		# print optionsResult
		sheetHand.write(examEndId-1, 5, optionsResult)

	if oneExamDataDict['题目类型'].encode("utf-8") == '判断':
		sheetHand.write(examEndId-1, 5, '对;错')
	
	sheetHand.write(examEndId-1, 8, oneExamDataDict['难度等级'])
	
	if oneExamDataDict['题目类型'].encode("utf-8") == '代码':
		global dirctName
		global folderName
		global needToZipFlag
		needToZipFlag = 1 #标记 需要进行打包zip
		fileName = folderName + '-' +str(examEndId) + '.txt'
		# print fileName
		saveProgramToTxt(dirctName, fileName, oneExamDataDict['答案'])
		sheetHand.write(examEndId-1, 6, fileName)
	
	elif oneExamDataDict['题目类型'].encode("utf-8") == '填空':
		blankResult = dealWithBlank(oneExamDataDict['题干'].encode("utf-8"), oneExamDataDict['答案'].encode("utf-8"))
		# print blankResult
		sheetHand.write(examEndId-1, 4, blankResult)
	else:
		sheetHand.write(examEndId-1, 6, oneExamDataDict['答案'])


	sheetHand.write(examEndId-1, 7, oneExamDataDict['答案说明'])


# 解析每一行的数据
def analysisRowData(rowDataList):
	# print type(rowDataList)
	# print type(rowDataList[0].encode("utf-8"))

	# 使用2个全局变量，用来进行测试
	global examStartId
	global examEndId
	global rowNumInOneExam
	global oneExamStartEndFlag
	global dictLastKey
	global dictLastValue


	str1 = ''
	str2 = '';
	# 测试，把unicode码转换为str后，是否相等
	if type(rowDataList[0]) == type(3.14):
		return

	str1 = rowDataList[0].encode("utf-8")

	if type(rowDataList[1]) == 'unicode':
		str2 = rowDataList[1].encode("utf-8")
	else:
		str2 = rowDataList[1]

	# print str1,str2

	# 在正式写入题目之前先写标题
	sheetHand.write(0, 0, '题型')
	sheetHand.write(0, 1, '知识体系名称')
	sheetHand.write(0, 2, '知识点')
	sheetHand.write(0, 3, '关键字')
	sheetHand.write(0, 4, '题干')
	sheetHand.write(0, 5, '选项')
	sheetHand.write(0, 6, '答案')
	sheetHand.write(0, 7, '答案说明')
	sheetHand.write(0, 8, '难度')

	findKey1 = "关键字"
	findKey2 = "题干"

	# 找“题干”这就是一道题目的开始
	if str1.find(findKey2) == 0:
		print "==========第%02d题（开始）==========="%examStartId
		oneExamDataDict.clear()
		examStartId += 1
		oneExamStartEndFlag = 1

	if oneExamStartEndFlag:
		if str1:
			str1 = str1.strip()
			if (dictLastKey != '') and (dictLastKey != str1):
				# print dictLastKey
				# print dictLastValue
				# 设置一个新的key
				oneExamDataDict[dictLastKey] = dictLastValue

			dictLastKey = str1


			if str1 == '题目类型':
				str2 = str2.strip()


			# 清空上次的value值
			dictLastValue = ''
		else:
			dictLastValue += '\n'


		if type(str2) == type(100):
			dictLastValue = dictLastValue + str(str2)
		if type(str2) == type(3.14):
			# print type(str2)
			dictLastValue = dictLastValue + "%.0f"%str2
		else:
			dictLastValue = dictLastValue + str2

		# print '    ',dictLastValue


	# 找“关键字”这就是一道题目的结束
	if str1.find(findKey1) == 0:
		
		
		oneExamStartEndFlag = 0
		
		# print dictLastKey
		# print dictLastValue
		oneExamDataDict[dictLastKey] = dictLastValue

		dictLastKey = ''
		print "==========第%02d题（结束）==========="%examEndId
		

		# 遍历 字典，其中存储就是一道题目详细信息
		# for k in oneExamDataDict:
		# 	print "dict[%s] =" % k,oneExamDataDict[k]

		# 将此题目写入到excel中
		write_excel(examEndId, oneExamDataDict);

		examEndId += 1

	
	rowNumInOneExam += 1

def read_excel():
	global needToAnalysisExcelName
	# 打开文件
	workbook = xlrd.open_workbook(needToAnalysisExcelName)
	# # 获取所有sheet
	# print workbook.sheet_names() # [u'sheet1', u'sheet2']
	# willOpenSheetName = workbook.sheet_names()[0] #注意下标是从0开始的
	# print '现在要打开的sheet为:'
	# print willOpenSheetName

	# 根据sheet索引或者名称获取sheet内容
	willOpenSheetName = workbook.sheet_by_index(0) # sheet索引从0开始
	# willOpenSheetName = workbook.sheet_by_name('willOpenSheetName')

	# sheet的名称，行数，列数
	print '现在要打开的sheet为:',willOpenSheetName.name
	print '总行数:',willOpenSheetName.nrows
	print '总列数:',willOpenSheetName.ncols

	# 获取整行和整列的值（数组）
	for x in xrange(0,willOpenSheetName.nrows):
		rows = willOpenSheetName.row_values(x) # 注意是从0开始的
		analysisRowData(rows);

#创建excel表
def createExcel():
	global excelHand
	global sheetHand
	#创建工作簿
	excelHand = xlwt.Workbook(encoding='utf-8')
	#创建sheet
	sheetHand = excelHand.add_sheet(u'Sheet1', cell_overwrite_ok=True) 

	# print type(sheetHand)

#保存数据到excel表
def saveExcel():
	global excelHand
	global dirctName
	excelHand.save( dirctName + '/' + dirctName + '.xls');

# 获取指定路径下所有指定后缀的文件
# dir 指定路径
# ext 指定后缀，链表&不需要带点 或者不指定。例子：['xml', 'java']
def GetFileFromThisRootDir(dir,ext = None):
  allfiles = []
  needExtFilter = (ext != None)
  for root,dirs,files in os.walk(dir):
	for filespath in files:
	  filepath = os.path.join(root, filespath)
	  extension = os.path.splitext(filepath)[1][1:]
	  if needExtFilter and extension in ext:
		allfiles.append(filepath)
	  elif not needExtFilter:
		allfiles.append(filepath)
  return allfiles

#打包zip文件
def saveTxtToZip():
	global dirctName
	global folderName

	f = zipfile.ZipFile(dirctName + '/' + folderName +'.zip','w',zipfile.ZIP_DEFLATED)
	txtFileName = GetFileFromThisRootDir(dirctName, 'txt')
	
	txtFileNum = len(txtFileName)
	if txtFileNum:
		print ''
		print ''
		print "正在创建压缩包..."
		for name in txtFileName:
			print name
			f.write(name)
		print "压缩包已经创建完成，共打包%d个文件"%txtFileNum
	else:
		print "没有要打包的代码文件，因此没有创建zip"
	f.close()

#创建文件夹
def createFolderByExcelName(pathName):
	if os.path.exists(pathName):
		print "文件夹已经存储，不需要重新创建..."
	else:
		print "正在创建文件夹..."
		os.mkdir(pathName)

# 解析给main传递的参数
def analysisMainParameter(argvs):
	# 以excel文件名（不包含后缀）创建的文件夹的路径
	global dirctName
	global folderName

	# 用来存储要解析的excel文件的名字
	global needToAnalysisExcelName
	argc = len(argvs)

	# 如果参数过少，进行相应的提示
	if argc == 1:
		print '请重新运行程序，按照以下要求:'
		print 'python exportExcelDataByOrder.py excel文件名'
		exit()

	if argc == 2:
		# 遍历给main传递的参数,for test
		# for argv in argvs:
		# 	print argv

		# 获取第二个参数
		needToAnalysisExcelName = argvs[1];

		# 判断获取的是否是excel文件的名字，通过后缀来判断
		indexInStr = needToAnalysisExcelName.find('.xlsx')
		if indexInStr != -1:
			folderName = needToAnalysisExcelName[:indexInStr]
			dirctName = './' + folderName
		else:
			indexInStr = needToAnalysisExcelName.find('.xls')
			if indexInStr != -1:
				folderName = needToAnalysisExcelName[:indexInStr]
				dirctName = './' + folderName	

		if dirctName != '':
			createFolderByExcelName(dirctName)
		else:
			print "请传递excel的文件名（包含后缀）"


# main函数
if __name__ == '__main__':

	global needToZipFlag

	# 解析给main传递的参数，根据这些信息可以创建文件夹，然后就组织路径
	analysisMainParameter(sys.argv)

	# 1. 创建工作薄
	createExcel()

	# 2. 读取excel中的题库内容
	read_excel()

	# 3. 保存excel文件
	saveExcel()

	# 4. 打包为zip
	if needToZipFlag:
		saveTxtToZip()

	print ''
	print ''
	print "========== 已完成导入到excel中，O(∩_∩)O哈哈~ ==========="
	print ''
	print ''
